hashlib 模块提供了常见的摘要算法(也称为: 哈希算法,hash算法),如 MD5,SHA1 等等。
什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
摘要算法是不可逆的,就是不能通过已经使用 md5 加密过的值推导计算出原来的值
摘要算法的用途:
- 密码的密文存储
- 文件的一致性验证
- 在下载的时候 检查我们下载的文件和远程服务器上的文件是否一致
- 两台机器上的两个文件 你想检查这两个文件是否相等
1. md5 -> 推荐使用
- .update(bytes) -> update方法所传入的值必须是 bytes 类型的加密内容
import hashlib
md5 = hashlib.md5()
md5.update(bytes('md5', encoding='utf-8')) # 必须传入 bytes 类型的值
digest = md5.digest() # 获取加密后的值,以二进制的形式返回,且是bytes类型
print(digest) # b'\x1b\xc2\x9b6\xf6#\xba\x82\xaa\xf6rO\xd3\xb1g\x18'
hexdigest = md5.hexdigest() # 获取加密后的值,以十六进制的形式返回 -> 推荐使用
print(hexdigest) # 1bc29b36f623ba82aaf6724fd3b16718
2. sha 系列
- sha系列 随着算法复杂程度的增加所摘要的时间成本和空间成本(占内存)都会增加,但是其安全性比较高
import hashlib
md5 = hashlib.sha1()
md5.update(bytes('md5', encoding='utf-8'))
ciphertext = md5.hexdigest()
print(ciphertext) # c1ea94f7e524679d0cf34ab7b0b28abe41ba732b
import hashlib
md5 = hashlib.sha224()
md5.update(bytes('md5', encoding='utf-8'))
ciphertext = md5.hexdigest()
print(ciphertext) # 9f1a17462e4842ba55e6378178242a9a5e8840f83e2bf6c0e2faacc3
4.分次调用 update() 方法
- 如果数据量很大,可以将内容分开分次调用update()
- 将内容分开分次调用update() 和 将全部内容一次性传给update() 所得到的结果都是一样的
# 将内容分开分次调用update()
import hashlib
md5 = hashlib.md5()
md5.update(bytes('Hello ', encoding='utf-8'))
md5.update(bytes('World', encoding='utf-&'))
ciphertext = md5.hexdigest()
print(ciphertext) # b10a8db164e0754105b7a99be72e3fe5
# 将全部内容一次性传给update()
import hashlib
md5 = hashlib.md5()
md5.update(bytes('Hello World', encoding='utf-8'))
ciphertext = md5.hexdigest()
print(ciphertext) # b10a8db164e0754105b7a99be72e3fe5
5. 加盐
- 加盐就是添加额外的内容与要加密的内容一起加密为了提交安全性,因为很多用户喜欢用123456,888888,password这些简单的口令,于是,黑客可以事先计算出这些常用口令的MD5值,得到一个反推表,这样,无需破解,只需要对比数据库的MD5,黑客就获得了使用常用口令的用户账号。
- hashlib.md5(bytes('加盐的内容', encoding='utf-8')) -> 加盐的内容,且加盐的内容必须是bytes类型
import hashlib
md5 = hashlib.md5(bytes('加盐', encoding='utf-8')) # 加盐的内容,且加盐的内容必须是bytes类型
md5.update(bytes('123456', encoding='utf-8')) # 需要加密的内容
pwd = md5.hexdigest()
print(pwd) # b5ef5feaf160038526b424e53a6fad9c
6. 动态加盐
- 使用用户名的一部分 或者 直接使用整个用户名作为盐
import hashlib
username = input('用户名:')
password = input('密码:')
md5 = hashlib.md5(bytes(username, encoding='utf-8')) # 以用户名作为动态的盐
md5.update(bytes(password, encoding='utf-8'))
pwd = md5.hexdigest()
print(pwd)
7. 练习
- 登录验证
import hashlib
# 用户名和密码应该从文件或者数据库中获取出来,这里为了方便所以写死在这里
usn = 'Kevin'
c_pwd = '54cf3f7e747ca9d7640f241ce949e565'
username = input('用户名:')
password = input('密码:')
md5 = hashlib.md5(bytes(username, encoding='utf-8')) # 用用户名作为盐
md5.update(bytes(password, encoding='utf-8'))
password = md5.hexdigest()
if username == usn and password == c_pwd:
print('登录成功')
else:
print('登录失败')
- 对一个文件进行摘要算法且需要分次 update(),最后计算出这个文件的md5值。
import hashlib
def file(name):
with open(name, encoding='utf-8') as f:
yield from f
def ciphertext_fn(f):
md5 = hashlib.md5()
for i in f:
md5.update(bytes(i, encoding='utf-8'))
return md5.hexdigest()
f = file('log.txt')
ciphertext = ciphertext_fn(f)
print(ciphertext) # 14b8cc85594b2cb47e5c1fac1ccce64c